<?php


require_once(dirname(__FILE__).'/../../common/log.php');
require_once(dirname(__FILE__).'/../../common/defines.php');
require_once(dirname(__FILE__).'/../../common/return.php');
require_once(dirname(__FILE__).'/../../database/mysql.class.php');
require_once(dirname(__FILE__).'/../../database/redis.class.php');

require_once(dirname(__FILE__).'/common.php');


$body  = file_get_contents('php://input');   
logd("recv: ".$body);

$data  = json_decode($body, true);
if ((!isset($data['userId'])) || (!isset($data['type'])) || (!isset($data['data'])))
{
    loge("params error: ".$body);

    failure(ERR_PARAM);
}

$userId    = $data['userId'];

//连接数据库
$mysql  = new mysqldb();
$ret    = $mysql->open_db(['dbname' => 'love-hole']);
if ($ret === FAILURE)
{
    failure(ERR_SYSTEM);
}

$umid  = make_umid($userId, $kefuId);
//将当前消息存入数据库
save_message($mysql, $userId, USERID_SERVER, $data['type'], json_encode($data['data'], JSON_UNESCAPED_UNICODE), 0, make_umid($userId, USERID_SERVER));

$redis  = new RedisUtils();
$redis->select(7);

do
{
    $kefuId  = get_current_kefu($redis, $userId);
    if ($kefuId == USERID_SERVER)
    {
        //未分配到客服时，将用户加入待分配列表
        $redis->rpush("server:waiting", $userId);

        success();
    }

    //检查当前客服是否在线（因为有可能刚分配成功，该客服就离线了）
    //尝试获取当前客服的互斥锁。这里必须先对当前客服加锁（加锁成功与否都无法唯一判断当前客服是否在线，所以不对加锁结果进行判断），否则当前客服在线状态可能不准确。
    //例如，假设已获取到的客服A此时刚好离线，则可能存在以下情况：
    //如果不加锁，假设下面zscore之后客服A才被客服离线线程zrem掉(并把数据库中客服A未回复的消息转发给其他客服)，那么当前线程并不知道客服A实际已离线，会继续将当前消息发送给客服A，造成当前消息无人处理。
    //如果先加锁，假设当前线程先锁住，客服离线线程会等待本线程把当前消息写入数据库；假设当前线程后锁住，那么下面zscore就会正确判断出客服A已离线
    //获取互斥锁失败表示：1、当前客服正处于离线中（因为客服离线的时候会加锁）；2、正在为当前客服分配另一个用户的消息
    //获取互斥锁成功表示：1、当前客服在线；2、当前客服刚离线完成，刚释放离线锁
    $kefuLock  = "server:kefuLock:$kefuId";
    $redis->try_lock($kefuLock);
    //通过获取客服分数判断当前客服是否在线
    //获取失败：当前客服已离线，需要重新为当前用户分配客服
    //获取成功：当前客服在线，正常继续流程
    $ret  = $redis->zscore("server:online", $kefuId);
    if (empty($ret))
    {
        //重新为当前用户分配客服
        $redis->hdel("server:current", $userId);
        $redis->unlock($kefuLock);
    }
} while (empty($ret));

//获取该用户未被其他客服回复的消息，重新发送给当前客服
$ret  = recv_other_message($mysql, $userId, $kefuId);
//增加当前客服的分数
if ($ret > 0)
{
    $redis->zincrby("server:online", $ret, $kefuId);
}

//对当前客服解锁
$ret  = $redis->unlock($kefuLock);
if ($ret === FAILURE)
{
    loge("unlock $kefuLock failed !");
}

success();
